package bot

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"os"
	"os/exec"
	"time"

	"gitee.com/daysleep/wechatBot/tool"
)

type BotAPI struct {
	Client *http.Client
}

func (botapi *BotAPI) MakeRequest(_url string, _methods string, _queryparams map[string]string, _formparams interface{}) string {
	if len(_queryparams) > 0 {
		_url += "?"
		for key, value := range _queryparams {
			_url += fmt.Sprintf("%v=%v&", key, value)
		}
	}
	var res *http.Response
	switch _methods {
	case "get":
		res, _ = botapi.Client.Get(_url)
	case "post":
		formjson, _ := json.Marshal(_formparams)
		res, _ = botapi.Client.Post(_url, "application/json", bytes.NewReader(formjson))
	}
	var body []byte
	if res != nil && res.Body != nil {
		defer res.Body.Close()
		body, _ = ioutil.ReadAll(res.Body)
	}
	return string(body)
}

func GetNewBot() *BotAPI {
	gCookieJar, _ := cookiejar.New(nil)
	return &BotAPI{Client: &http.Client{Jar: gCookieJar}}
}

func (botapi *BotAPI) GetUuid() (string, error) {
	url := "https://login.web.wechat.com/jslogin"
	m := make(map[string]string)
	m["appid"] = "wx782c26e4c19acffb"
	m["redirect_uri"] = "https%3A%2F%2Fweb.wechat.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage"
	m["fun"] = "new"
	m["_"] = tool.IntToString(time.Now().UnixNano())
	str := botapi.MakeRequest(url, "get", m, nil)
	uuid := tool.GetByRegexp(str, `window.QRLogin.uuid = "`)
	return uuid, nil
}

func (botapi *BotAPI) GenQRcode(_uuid string) {
	path := "qrcode.jpg"
	res, _ := botapi.Client.Get("https://login.weixin.qq.com/qrcode/" + _uuid)
	out, _ := os.Create(path)
	io.Copy(out, res.Body)
	exec.Command("open", path).Run()
}

func (botapi *BotAPI) Login(_uuid string) string {
	url := "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login"
	queryparams := map[string]string{
		"loginicon": "true",
		"uuid":      _uuid,
		"tip":       "0",
		"r":         tool.GetRandom(),
		"_":         fmt.Sprintf("%v", time.Now().UnixNano()),
	}

	var str, code string
	for code != "200" {
		str = botapi.MakeRequest(url, "get", queryparams, nil)
		code = tool.GetByRegexp(str, "window.code=")
	}
	redirect_uri := tool.GetByRegexp(str, `window.redirect_uri="`)
	return redirect_uri
}

type Info struct {
	Ret         string `xml:"ret"`
	Message     string `xml:"message"`
	Skey        string `xml:"skey"`
	Wxsid       string `xml:"wxsid"`
	Wxuin       string `xml:"wxuin"`
	Pass_ticket string `xml:"pass_ticket"`
	Isgrayscale string `xml:"isgrayscale"`
}

func (botapi *BotAPI) LoginInfo(_url string) *Info {
	_url += "&fun=new&version=v2"
	str := botapi.MakeRequest(_url, "get", nil, nil)
	info := Info{}
	xml.Unmarshal([]byte(str), &info)
	return &info
}

type BaseRequest struct {
	Uin      string
	Sid      string
	Skey     string
	DeviceID string
}

type BR struct {
	BaseRequest BaseRequest `json:"BaseRequest"`
}

func (botapi *BotAPI) WebwxInit(_pass_ticket string, _uin string, _sid string, _skey string) string {
	url := "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit"
	m := map[string]string{
		"r":           tool.GetRandom(),
		"pass_ticket": _pass_ticket,
	}
	b := BaseRequest{_uin, _sid, _skey, tool.GetDeviceID()}
	br := BR{b}
	str := botapi.MakeRequest(url, "post", m, br)
	f, _ := os.Open("init.log")
	f.Write([]byte(str))
	return str
}

func (botapi *BotAPI) SyncCheck(_uin string, _sid string, _skey string, synckey string) (string, string) {
	url := "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck"
	m := map[string]string{
		"skey":     _skey,
		"uin":      _uin,
		"synckey":  synckey,
		"sid":      _sid,
		"deviceid": tool.GetDeviceID(),
		"_":        fmt.Sprintf("%v", time.Now().UnixNano()),
		"r":        fmt.Sprintf("%v", time.Now().UnixNano()),
	}
	str := botapi.MakeRequest(url, "get", m, nil)
	// fmt.Println("SyncCheck:", str)
	retcode := tool.GetByRegexp(str, `retcode:"`)
	selector := tool.GetByRegexp(str, `selector:"`)
	return retcode, selector
}

func (botapi *BotAPI) WebwxSync(_uin string, _sid string, _skey string, _passticket string, _sk tool.SK) string {
	url := "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync"
	m := map[string]string{
		"sid":         _sid,
		"skey":        _skey,
		"pass_ticket": _passticket,
		"lang":        "zh_CN",
	}
	type Sync struct {
		BaseRequest BaseRequest  `json:"BaseRequest"`
		SyncKey     tool.SyncKey `json:"SyncKey"`
		RR          int          `json:"rr"`
	}
	b := BaseRequest{_uin, _sid, _skey, tool.GetDeviceID()}
	var sync Sync = Sync{b, _sk.SyncKey, ^int(time.Now().Unix())}
	str := botapi.MakeRequest(url, "post", m, sync)
	return str
}

type PostMsg struct {
	BaseRequest BaseRequest `json:"BaseRequest"`
	Msg         Msg         `json:"Msg"`
	Scene       int         `json:"Scene"`
}
type Msg struct {
	ClientMsgId  string `json:"ClientMsgId"`
	Content      string `json:"Content"`
	FromUserName string `json:"FromUserName"`
	ToUserName   string `json:"ToUserName"`
	LocalID      string `json:"LocalID"`
	Type         int    `json:"Type"`
}

func (botapi *BotAPI) SendMsg(_uin string, _sid string, _skey string, _passticket string, _msg string, _from string, _to string) {
	url := "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg"
	m := map[string]string{
		"pass_ticket": _passticket,
		"lang":        "zh_CN",
	}
	b := BaseRequest{_uin, _sid, _skey, tool.GetDeviceID()}
	temp := fmt.Sprintf("%v%v", time.Now().UnixNano(), tool.GetRandom4()) + tool.GetRandom4()
	var msg Msg = Msg{temp, _msg, _from, _to, temp, 1}
	var postMsg PostMsg = PostMsg{b, msg, 0}
	botapi.MakeRequest(url, "post", m, postMsg)
	// fmt.Println("sendmsg=", str)
}

//https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r=1533284916291&seq=0&skey=@crypt_6bd85d64_f9ffa55c6ded9c1f4543da8b9d0d78c3
// r: 1533284916291
// seq: 0
// skey: @crypt_6bd85d64_f9ffa55c6ded9c1f4543da8b9d0d78c3

func (botapi *BotAPI) GetAllUsers(_skey string) string {
	url := "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?r=1533284916291&seq=0&skey=@crypt_6bd85d64_f9ffa55c6ded9c1f4543da8b9d0d78c3"
	m := map[string]string{
		"skey": _skey,
		"seq":  "0",
		"r":    fmt.Sprintf("%v", time.Now().UnixNano()),
	}
	str := botapi.MakeRequest(url, "get", m, nil)
	fmt.Println(str)
	return str
}
